//Wrapper for EE::Application
#pragma once

namespace EsenthelNet
{	
	/// <summary>
	/// Application Flags
	/// </summary>
	public enum class AppFlags { 
		/// <summary>Application window will have no caption</summary>
		No_Caption        =1<< 0,
		/// <summary>Application won't be closed by Alt+F4 or when recevied one of the following messages in window loop : WM_QUIT WM_CLOSE WM_DESTROY</summary>
		No_Close          =1<< 1, 
		/// <summary>Application will have minimize box on the window</summary>
		Minimizable       =1<< 2, 
		/// <summary>Application will have maximize box on the window</summary>
		Maximizable       =1<< 3,
		/// <summary>Application window can be resized by dragging the window edges/corners</summary>
		Resizable         =1<< 4, 
		/// <summary>Display can be altered with Alt+Enter keys (windowed/fullscreen toggle), Alt+Shift+Enter can also be used to switch into fullscreen with resolution taken from the window size</summary>
		Full_Toggle       =1<< 5,
		/// <summary>Application will work also in background (when not focused)</summary>
		Work_In_Background=1<< 6, 
		/// <summary>If the application is already running in another instance then exit</summary>
		On_Run_Exit       =1<< 7, // 
		/// <summary>If the application is already running in another instance then wait until it exits and then continue</summary>
		On_Run_Wait       =1<< 8, 
		/// <summary>Init keyboard in exclusive mode (which disables windows key)</summary>
		Kb_Exclusive      =1<< 9,
		/// <summary>Init mouse in exclusive mode (which hides cursor and clips it to the window)</summary>
		Ms_Exclusive      =1<<10,
		/// <summary>Close mouse driver (Ms.driver_name) when application starts, and restore it later</summary>
		Ms_Driver_close   =1<<11, 
		/// <summary>Kill  mouse driver (Ms.driver_name) when application starts, and restore it later</summary>
		Ms_Driver_kill    =1<<12,
		/// <summary>Error will be shown at program exit if memory leaks were found, use only for debugging as it may slow down the application</summary>
		Mem_leaks         =1<<13,
		/// <summary>Application will perform only basic graphics, render targets won't be created, application will start faster and use less memory</summary>
		No_Fx             =1<<14,
		/// <summary>Allow forward rendering, this will load additional shaders and thus make the application start longer and use more memory, this flag is valid only with APP_NO_FX disabled</summary>
		Allow_RT_Forward  =1<<15, 
		/// <summary>This flag specifies that DirectX should handle data management instead of the Graphics Driver (used only in DX9)</summary>
		DX_Management     =1<<16, 
		/// <summary>This flag specifies that DirectX should be multi-threaded safe, this slows down all DirectX calls and makes rendering slower, the engine is already multi-thread safe when it comes to managing GPU resources, which means that this flag is not needed when performing operations on different GPU resources on multiple threads, use this only for debugging if you suspect DirectX/Driver error</summary>
		DX_Thread_Safe    =1<<17
	 }; 

	//Used for dopping event
	extern void _dropped();

	/// <summary>Application Settings</summary>
	public ref class Application
	{
	internal:
		static EsenthelNet::Application^ Instance;
		
		void OnDrop() {
			Dropped();
		}
		Application() {
			Instance = this;
			App.drop = *static_cast<void(*)()>(_dropped);
		}

	public:
		/// <summary>Initial x position (-1..1) used to specify window position on the desktop at the creation of application, default=(-1,1)</summary>
		Prop(int, X, App.x)			
		/// <summary>Initial y position (-1..1) used to specify window position on the desktop at the creation of application, default=(-1,1)</summary>
		Prop(int, Y, App.y)	


		/// <summary>Event gets called when a file is Drag and Dropped on the application window</summary>
		event EmptyDelegate^ Dropped;

		/// <summary>APP_FLAG</summary>
		property EsenthelNet::AppFlags Flag {
			EsenthelNet::AppFlags get() {
				return (EsenthelNet::AppFlags)App.flag;
			}
			void set(EsenthelNet::AppFlags flag) {
				App.flag = (UInt)flag;
			}
		}

		///<summary>Get/Set the application name.</summary>
		PropMetString(Name, App.name)
		///<summary>Get Executable Path and Name</summary>
		PropMetStringGet(ExeFile, App.exe)
		///<summary>Get received Command Line Parameters</summary>
		PropMetStringGet(CmdLine, App.cmdLine)

		///<summary>If  Application is Active</summary>
		PropMetGet(bool, IsActive, App.active)
		///<summary>If  Application is Minimized</summary>
		PropMetGet(bool, IsMinimized, App.minimized)
		///<summary>If  Application is Maximized</summary>
		PropMetGet(bool, IsMaximized, App.maximized)
		
		///<summary>Get Application Window Handle in the OS</summary>
		property System::IntPtr^ Handle { System::IntPtr^ get() { return gcnew System::IntPtr(App.hwnd()); } }

		///<summary>Get screen width at the moment of application start (desktop width)</summary>
		PropMetGet(int, DesktopWidth, App.desktopW)
		///<summary>Get screen height at the moment of application start (desktop height)</summary>
		PropMetGet(int, DesktopHeight, App.desktopH)
		///<summary>Get screen width  at the current moment)</summary>
		PropMetGet(int, ScreenWidth, App.screenW)
		///<summary>Get screen height  at the current moment</summary>
		PropMetGet(int, ScreenHeight, App.screenH)

		///<summary>Set current directory, this is equal to calling the system 'SetCurrentDirectory' function.</summary>
		void SetCurDir(System::String^ dir) {
			App.setCurDir(ToEEStr(dir));
		}

		///<summary>Rename self exe to 'dest' location, false on fail.</summary>
		bool RenameSelf(System::String^ dest) {
			return App.renameSelf(ToEEStr(dest));
		}

		///<summary>Notify that the exe should delete itself at application exit (this works by creating a temporary .bat file which deletes the exe and itself).</summary>
		void DeleteSelfAtExit() {
			App.deleteSelfAtExit();
		}

		///<summary>Deletes the instance.</summary>
		~Application() {
			delete Dropped;
			delete Instance;
		}
	};

}

